package com.sojson.util.search.es.config;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.http.HttpHeaders;

import com.sojson.constant.Constant;
import com.sojson.util.search.es.condition.EsCondittion;
import com.sojson.util.text.Convert;

import cn.hutool.core.util.StrUtil;

/**
 * ES配置类
 * 
 * @author liu
 * @date 2022-07-21
 */
@Configuration
/** 类似Mybatis的@MapperScan,区别是里面的增删改查不需要写,已经写好了 */
@EnableElasticsearchRepositories(basePackages = {"**.es.**.repository.**"})
/** 是否注入这个Bean */
@Conditional(EsCondittion.class)
public class EsConfig {

    /** 服务器地址(集群模式) */
    public static final String ADDRS = Constant.PROPERTIES.getProperty("so.search.es.addrs");
    /** 服务器帐号 */
    public static final String USERNAME = Convert.toStr(Constant.PROPERTIES.getProperty("so.search.es.username"), "es");
    /** 服务器密码 */
    public static final String PASSWORD = Convert.toStr(Constant.PROPERTIES.getProperty("so.search.es.password"), "es");
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int CONNECT_TIME_OUT =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.connectTimeOut"), 1000 * 10);
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int SOCKET_TIME_OUT =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.socketTimeOut"), 1000 * 10 * 5);
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int CONNECTION_REQUEST_TIME_OUT =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.connectionRequestTimeOut"), 1000 * 10);
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int MAX_CONNECT_NUM =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.maxConnectNum"), 30);
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int MAX_CONNECT_PER_ROUTE =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.maxConnectPerRoute"), 10);
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int KEEP_ALIVE_MINUTES =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.keepAliveMinutes"), 10);
    /** 连接断开后重新连接的间隔时间(单位: 毫秒,默认10秒) */
    public static final int PAGE_SIZE =
        Convert.toInt(Constant.PROPERTIES.getProperty("so.search.es.pageSize"), 1000 * 10);

    /**
     * ES连接处理类
     * 
     * @return
     */
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        String[] addrs = ADDRS.split(",");
        int addrsLen = addrs.length;

        HttpHost[] httpPostArr = new HttpHost[addrsLen];
        for (int i = 0; i < addrsLen; i++) {
            String[] split = addrs[i].split(":");
            httpPostArr[i] =
                new HttpHost(split[0].trim(), split.length > 1 ? Integer.parseInt(split[1]) : 9200, "http");
        }
        RestClientBuilder builder = RestClient.builder(httpPostArr);
        HttpHeaders httpHeaders = new HttpHeaders();
        // 密码
        if (StrUtil.isNotBlank(USERNAME) && StrUtil.isNotBlank(PASSWORD)) {
            httpHeaders.setBasicAuth(USERNAME, PASSWORD);
            Header[] headers = httpHeaders.entrySet().stream() //
                .flatMap(entry -> entry.getValue().stream() //
                    .map(value -> new BasicHeader(entry.getKey(), value))) //
                .toArray(Header[]::new);
            builder.setDefaultHeaders(headers);
        }

        // 异步httpclient连接延时配置
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(CONNECT_TIME_OUT);
            requestConfigBuilder.setSocketTimeout(SOCKET_TIME_OUT);
            requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIME_OUT);
            // HttpHost proxy = new HttpHost("127.0.0.1", 22, "http");
            // requestConfigBuilder.setProxy(proxy);
            return requestConfigBuilder;
        });

        // 异步httpclient配置
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            // httpclient连接数配置
            httpClientBuilder.setMaxConnTotal(MAX_CONNECT_NUM);
            httpClientBuilder.setMaxConnPerRoute(MAX_CONNECT_PER_ROUTE);
            // httpclient保活策略
            httpClientBuilder.setKeepAliveStrategy(CustomConnectionKeepAliveStrategy.getInstance(KEEP_ALIVE_MINUTES));
            return httpClientBuilder;
        });
        return new RestHighLevelClient(builder);
    }

}